<template>
  <div id="compare">
    <magic-header titleName="车型比较">
      <span class="title-r" slot="title-right" v-if="!isHideSameItem && products.length > 1" v-tap.stop="{methods: toggleSameItem, res: true}">隐藏相同</span>
      <span class="title-r" slot="title-right" v-if="isHideSameItem && products.length > 1" v-tap.stop="{methods: toggleSameItem, res: false}">显示全部</span>
    </magic-header>
    <div class="compare-content" :class="{'transcroll': isTranscroll}">
      <!-- title -->
      <section class="section-title">
        <div class="car-title">
          <!-- label -->
          <div class="param-title">
            <span>车型比较</span>
          </div>
          <!-- car -->
          <div class="param-content">
            <div class="scroll0" :style="scroll0" id="scroll0">
              <span v-for="(product,index) in products" :key="index">
                {{product.name}}
                <!-- <mu-icon v-if="productId ? index > 0 : index >= 0" class="cancel-image" value="cancel" v-tap.stop="{methods: removeProduct, index: index}"></mu-icon> -->
                <i v-if="productId ? index > 0 : index >= 0" class="cancel-image iconfont" value="cancel" v-tap.stop="{methods: removeProduct, index: index}">&#xe622;</i>
              </span>
              <span v-tap.stop="{methods: addProduct}" class="add">
                <img :src="addIcon" alt="">
              </span>
            </div>
          </div>
        </div>
      </section>
      <section class="common-title">
        <!-- 公共展示的参数项 -->
        <div class="param-group-name" :style="paramGroupName">
          <span>
            {{commonParamGroupName}}
          </span>
          <span>
            <span class="circle-solid"></span> 标配
            <span class="circle-hollow"></span> 选配
            <span>-</span> 无
          </span>
        </div>
      </section>
      <!-- param -->
      <section class="section-param">
        <div class="param-items">
          <!-- label -->
          <div class="param-title">
            <div class="scroll1" :style="scroll1" id="scroll1">
              <div class="param-title-content" v-for="(paramGroup, paramGroupIndex) in paramGroups" :key="paramGroupIndex">
                <div class="param-group-name" :style="paramGroupName" v-if="paramGroupIndex>0">{{paramGroup.name}}</div>
                <span class="param-title-item" v-for="(parameter, parameterIndex) in paramGroup.parameters" :key="parameterIndex">
                  {{parameter.name}}
                </span>
              </div>
            </div>
          </div>
          <!-- value -->
          <div class="param-content">
            <div class="scroll2" :style="scroll2" id="scroll2">
              <div class="param-content-content" v-for="(paramGroup, paramGroupIndex) in paramGroups" :key="paramGroupIndex">
                <div style="height:30px;" v-if="paramGroupIndex > 0">&nbsp;</div>
                <div class="param-content-items" :class="{'param-content-items-bg': !isSame(parameter.productsParamValue)}" v-for="(parameter, parameterIndex) in paramGroup.parameters" :key="parameterIndex">
                  <span class="param-content-item" v-for="(productParamValue, productParamValueIndex) in parameter.productsParamValue" :key="productParamValueIndex" @click="getMessage(productParamValue, $event)">
                    {{productParamValue}}
                  </span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>

<script>
// components
import magicHeader from "components/magicHeader";
// images
import addIcon from "assets/add-img.png";
// Store
import carStore from "services/seeGoods/car-compare";

const HEADER_HEIGHT = 50;
const GROUP_NAME_HEIGHT = 30;
const PARAM_VALUE_HEIGHT = 50;
const ITEM_WIDTH = 100;
const TITLE_ITEM_HEIGHT = 100;
const WINDOW_WIDTH = window.innerWidth;
const WINDOW_HEIGHT = window.innerHeight;
export default {
  components: { magicHeader },
  data() {
    return {
      addIcon,
      // style
      scroll0: {},
      scroll1: {},
      scroll2: {},
      isHideSameItem: false, // 是否隐藏相同项
      paramGroupName: {},
      // data
      // commonParamGroupName: "111",
      productId: "", // productId为空时, 表示入口为原生, 直接选择车型进入车辆对比, 而不是从商品详情进入的, 下面代码中有几处相应判断 productId ? xx : yy
      productIds: [],
      products: [],
      paramGroups: [],
      paramLabelTransformYMapper: [],
      // 滚动事件的坐标及元素
      isTranscroll: false,
      scroll0Dom: null,
      scroll1Dom: null,
      scroll2Dom: null,
      startX: 0,
      startY: 0,
      scrollX: 0,
      scrollY: 0,
      currentX: 0,
      currentY: 0,
      translateX: 0,
      translateY: 0,
      direction: "row", // row-横 column-竖
      ratio: 1, // 跟手率
      getDirection: false,
      fromRoute: '' // 路由来源
    };
  },
  computed: {
    commonParamGroupName() {
      let _index = 0;

      this.paramLabelTransformYMapper.forEach((item, index) => {
        if (-this.translateY > item.val) {
          _index = index + 1;
          return;
        }
      });
      return (
        this.paramLabelTransformYMapper[_index] &&
        this.paramLabelTransformYMapper[_index].name
      );
    }
  },
  created() {
    this.$nextTick(() => {
      if (this.fromRoute != '_selectCar' && this.fromRoute != 'selectCar') {
        carStore.commit("setId", '')
        carStore.commit("setIds", [])
      }
      // id init
      this.productId = this.$route.params.id;
      carStore.commit("setId", this.productId);
      this.productIds = carStore.getters.getIds;

      this.init();
    })
  },
  beforeRouteEnter(to, from, next) {
    next(vm => {
      // 如果不是从车型选择进入的话, 清空store
      vm.fromRoute = from.name;
      carStore.commit("setRouteStatusPush", false)
    })
  },
  methods: {
    // init
    init() {
      let vm = this;
      // 查询需要对比的产品参数项和参数值
      this.queryProductCompare().then(function () {
        // 0. style
        vm.setDOMStyle();
        // 1. 获取参数项, 首次进入, 只能获取到一个product, 以此为基准, 进行对比操作
        // 不同车型之间的不同配置项需要做合并 mixParameterGroups
        let parameterGroups = vm.mixProductParameterGroups(vm.products);
        vm.paramGroups = vm.getParameterGroups(parameterGroups, vm.products);
        // 2. 绑定touch事件
        vm.bindTouchScroll();
        // 3 scroll 参数
        vm.initLabelTransform();
      });
    },
    toggleSameItem(params) {
      this.isHideSameItem = params.res;
      this.init()
    },
    // 计算paramGroup的名字和在页面中的位置, 用来监控并更改公共group name时使用
    initLabelTransform() {
      let _base = 0;
      this.paramGroups.forEach(param => {
        this.paramLabelTransformYMapper.push({
          name: param.name,
          val:
            _base +
            param.parameters.length * PARAM_VALUE_HEIGHT +
            GROUP_NAME_HEIGHT
        });
        _base =
          _base +
          param.parameters.length * PARAM_VALUE_HEIGHT +
          GROUP_NAME_HEIGHT;
      });
    },
    // 动态计算 样式
    setDOMStyle() {
      this.scroll0.width = `${(this.products.length + 1) * ITEM_WIDTH + 1}px`;
      this.scroll1.width = `${ITEM_WIDTH}px`;
      this.scroll2.width = `${this.products.length * ITEM_WIDTH + 1}px`;
      this.paramGroupName.width = `${WINDOW_WIDTH}px`;
    },
    // touch时的transform值
    setTransformRow() {
      this.scroll0Dom.style.transform = `translate(${this.translateX}px, 0px)`;
      this.scroll2Dom.style.transform = `translate(${this.translateX}px, ${
        this.translateY
        }px)`;
    },
    // touch时的transform值
    setTransformColumn() {
      this.scroll1Dom.style.transform = `translate(0px, ${this.translateY}px)`;
      this.scroll2Dom.style.transform = `translate(${this.translateX}px, ${
        this.translateY
        }px)`;
    },
    // 配置项混合
    mixProductParameterGroups(products) {
      let allParameterGroups = []
      products.forEach(product => {
        allParameterGroups.push(JSON.parse(
          JSON.stringify(product.parameterGroups)
        ))
      })
      let baseParameterGroups = allParameterGroups[0];
      allParameterGroups.splice(0, 1)
      allParameterGroups.forEach(parameterGroups => {
        this.mixParameterGroups(baseParameterGroups, parameterGroups)
      })

      return baseParameterGroups
    },
    mixParameterGroups(baseParameterGroups, parameterGroups) {
      parameterGroups.forEach(parameterGroup => {
        let isSame = false
        baseParameterGroups.forEach(baseParameterGroup => {
          if (baseParameterGroup.id == parameterGroup.id) {
            isSame = true;
            this.mixParameters(baseParameterGroup.parameters, parameterGroup.parameters)
          }
        })
        if (!isSame) {
          baseParameterGroups.push(parameterGroup)
        }
      })
    },
    mixParameters(baseParameters, parameters) {
      parameters.forEach(parameter => {
        let isSame = false
        baseParameters.forEach(baseParameter => {
          if (parameter.id == baseParameter.id) {
            isSame = true;
          }
        })
        if (!isSame) {
          baseParameters.push(parameter)
        }
      })
    },
    // 获取参数项
    getParameterGroups(parameterGroups, products) {
      parameterGroups.forEach(parameterGroup => {
        parameterGroup.parameters.forEach(parameter => {
          parameter.productsParamValue = [];
          products.forEach(product => {
            let productParamValue = this.getProductParamValue(
              product,
              parameterGroup.id,
              parameter.id
            );
            parameter.productsParamValue.push(productParamValue);
          });
        });
      });

      this.isHideSameItem && products.length > 1 && this.hideSameItem(parameterGroups)
      return parameterGroups;
    },
    // 根据id获取参数值
    getProductParamValue(product, groupId, paramId) {
      const NULL_PARAM_VALUE = "-";
      // 指定的parameterGroup
      let [_parameterGroup] = product.parameterGroups.filter(parameterGroup => {
        return parameterGroup.id == groupId;
      });
      // 指定的parameter
      if (
        _parameterGroup &&
        _parameterGroup.parameters &&
        _parameterGroup.parameters.length > 0
      ) {
        let [_parameter] = _parameterGroup.parameters.filter(parameter => {
          return parameter.id == paramId;
        });

        if (_parameter) {
          return _parameter.value ? _parameter.value : NULL_PARAM_VALUE;
        }
      }
      return NULL_PARAM_VALUE;
    },
    // 隐藏相同项
    hideSameItem(parameterGroups) {
      let i, j;
      let temp
      for (i = 0; i < parameterGroups.length; i++) {
        for (j = 0, temp = parameterGroups[i].parameters; j < temp.length; j++) {
          // 是否是相同项
          let isSame = new Set(temp[j].productsParamValue).size == 1

          // 如果相同, 删除该数据
          if (isSame) {
            temp.splice(j, 1);
            j = j - 1;
          }
        }
        // 如果整个参数组都相同, 删除参数组
        if (parameterGroups[i].parameters.length == 0) {
          parameterGroups.splice(i, 1);
          i = i - 1;
        }
      }
    },
    // 绑定touch事件, 手动指定滚动方法
    bindTouchScroll() {
      this.$nextTick(() => {
        // 阻止橡皮筋效果
        this.stopElastic();
        // bind event listener
        let dom = document.querySelector(".compare-content");
        dom.addEventListener("touchstart", this.touchStart, false);
        dom.addEventListener("touchmove", this.touchMove, false);
        dom.addEventListener("touchend", this.touchEnd, false);

        this.scroll0Dom = document.querySelector("#scroll0");
        this.scroll1Dom = document.querySelector("#scroll1");
        this.scroll2Dom = document.querySelector("#scroll2");
      });
    },
    touchStart(e) {
      this.isTranscroll = false;
      this.startX = e.touches[0].pageX;
      this.startY = e.touches[0].pageY;
      // e.preventDefault();
      // e.stopPropagation();
    },
    touchMove(e) {
      let current;
      let x, y;
      if (!this.getDirection) {
        this.scrollX = e.touches[0].pageX;
        this.scrollY = e.touches[0].pageY;
        x = this.scrollX - this.startX;
        y = this.scrollY - this.startY;
        // 判断方向
        this.direction = Math.abs(x) / Math.abs(y) > 1 ? "row" : "column";
        this.getDirection = true;
      }

      this.scrollX = e.touches[0].pageX;
      this.scrollY = e.touches[0].pageY;
      x = (this.scrollX - this.startX) * this.ratio;
      y = (this.scrollY - this.startY) * this.ratio;

      switch (this.direction) {
        case "row":
          //x
          this.translateX = this.currentX + x;
          this.setTransformRow();
          break;
        case "column":
          //y
          this.translateY = this.currentY + y;
          this.setTransformColumn();
          break;
        default:
          break;
      }
    },
    touchEnd(e) {
      this.isTranscroll = true;
      this.getDirection = false;
      // console.log((this.products.length + 1) * 100, this.translateX);
      this.$nextTick(() => {
        this.elasticX();
        this.elasticY();
        this.currentX = this.translateX;
        this.currentY = this.translateY;
      });

      // console.log("touchEnd");
    },
    elasticY() {
      let scrollHeight = this.scroll1Dom.scrollHeight;
      if (
        this.translateY > 0 ||
        scrollHeight +
        TITLE_ITEM_HEIGHT +
        PARAM_VALUE_HEIGHT +
        GROUP_NAME_HEIGHT +
        HEADER_HEIGHT <
        WINDOW_HEIGHT
      ) {
        this.translateY = 0;
        this.setTransformColumn();
      } else if (
        scrollHeight +
        TITLE_ITEM_HEIGHT +
        PARAM_VALUE_HEIGHT +
        HEADER_HEIGHT +
        this.translateY <
        WINDOW_HEIGHT &&
        scrollHeight +
        TITLE_ITEM_HEIGHT +
        PARAM_VALUE_HEIGHT +
        GROUP_NAME_HEIGHT +
        HEADER_HEIGHT >
        WINDOW_HEIGHT
      ) {
        this.translateY =
          0 -
          (scrollHeight +
            HEADER_HEIGHT +
            GROUP_NAME_HEIGHT +
            TITLE_ITEM_HEIGHT -
            WINDOW_HEIGHT);
        this.setTransformColumn();
      }
    },
    elasticX() {
      if (
        this.translateX > 0 ||
        (this.products.length + 1) * ITEM_WIDTH + ITEM_WIDTH < WINDOW_WIDTH
      ) {
        this.translateX = 0;
        this.setTransformRow();
      } else if (
        (this.products.length + 1) * ITEM_WIDTH + ITEM_WIDTH + this.translateX <
        WINDOW_WIDTH &&
        (this.products.length + 1) * ITEM_WIDTH + ITEM_WIDTH > WINDOW_WIDTH
      ) {
        this.translateX =
          0 -
          ((this.products.length + 1) * ITEM_WIDTH + ITEM_WIDTH - WINDOW_WIDTH);
        this.setTransformRow();
      }
    },
    // 阻止橡皮筋效果
    stopElastic() {
      document.querySelectorAll("body")[0].addEventListener(
        "touchstart",
        function (e) {
          e.preventDefault();
        },
        false
      );
      document.addEventListener(
        "touchstart",
        function (event) {
          // 判断默认行为是否可以被禁用
          if (event.cancelable) {
            // 判断默认行为是否已经被禁用
            if (!event.defaultPrevented) {
              event.preventDefault();
            }
          }
        },
        false
      );
    },
    // 查询车型比较的产品信息
    queryProductCompare() {
      let vm = this;
      return new Promise(function (resolve, reject) {
        vm.$.get({
          methodName: "QueryProductCompare",
          productIds: vm.productId
            ? [vm.productId, ...vm.productIds]
            : vm.productIds
        }).then(resp => {
          // console.log(resp);
          vm.products = resp.data.products;
          resolve();
        });
      });
    },
    // 删除对比商品
    removeProduct(params) {
      this.productId
        ? this.productIds.splice(params.index - 1, 1)
        : this.productIds.splice(params.index, 1);
      this.products.splice(params.index, 1);
      this.paramGroups.forEach(paramGroup => {
        paramGroup.parameters.forEach(parameter => {
          parameter.productsParamValue.splice(params.index, 1);
        });
      });

      if (this.products.length == 0) {
        this.$router.back()
      } else if (this.products.length == 1) {
        this.isHideSameItem = false;
        this.init()
      }
    },
    // 增加对比商品
    addProduct() {
      carStore.commit("setRouteStatusPush", true)
      this.$router.push({
        name: "_selectCar",
        params: {
          is: "select"
        }
      });
    },
    // 信息展示不下时的弹窗展示
    getMessage(val, e) {
      // @TODO 暂时先简略展示
      // let pageX = e.pageX;
      // let pageY = e.pageY;
      // let tipDom = document.createElement(span);
    },
    isSame(arr) {
      let result = true;
      if (arr && arr.length > 0) {
        arr.reduce((pre, cur) => {
          if (pre == cur) {
            result = result && true;
          } else {
            result = result && false;
          }
          return pre;
        });
      } else {
        result = false;
      }
      return result;
    }
  }
};
</script>

<style lang="scss" scoped>
$item_width: 100px;
$item_height: 50px;
$item_title_height: 100px;
$group_title_height: 30px;
.compare-content {
  display: flex;
  flex-direction: column;
  flex-grow: 1;
  .car-title,
  .param-items {
    span {
      display: inline-block;
      border-right: solid #d7d7d7 1px;
      border-top: solid #d7d7d7 1px;
      color: #666;
      text-align: center;
    }
  }
  .car-title {
    span {
      width: $item_width;
      height: $item_title_height;
      position: relative;
      padding: $item_title_height/3 0;
      word-break: keep-all;
      .cancel-image {
        position: absolute;
        top: 0px;
        right: 0px;
      }
    }
  }
  .param-items {
    overflow: hidden;
    span {
      width: $item_width;
      height: $item_height;
      // line-height: $item_height;
      padding: 15px 0;
    }
    .param-content {
      .param-content-items {
        height: $item_height;
      }
      .param-content-items-bg {
        background: #e5edf9;
      }
      span {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }
    }
  }
  .param-content {
    overflow: hidden;
    flex-grow: 1;
  }
  .car-title,
  .car-title .param-content > div,
  .param-items {
    display: flex;
    flex-wrap: nowrap;
    justify-content: flex-start;
  }
}
.param-group-name {
  height: $group_title_height;
  position: relative;
  z-index: 1;
  padding: 10px 5px;
  font-size: 0.75rem;
  color: #666;
  background-color: #f0f0f0;
  border-top: solid #d7d7d7 1px;
  display: flex;
  justify-content: space-between;
  &:after {
    content: " ";
    position: absolute;
    left: 0;
    width: 100%;
    height: 0;
    border-bottom: solid #d7d7d7 1px;
    bottom: -1px;
  }
}
.common-title {
  &:after {
    content: " ";
    position: absolute;
    left: 0;
    width: 100%;
    height: 0;
    border-bottom: solid #d7d7d7 1px;
  }
}
.transcroll {
  .scroll0,
  .scroll1,
  .scroll2 {
    transition: all 0.5s cubic-bezier(0, 0, 0.21, 0.99);
  }
}
.section-param {
  overflow: hidden;
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  > div {
    flex-grow: 1;
  }
}

i.tril {
  transform: translate(3px, -10px) rotate(-45deg);
  display: inline;
  position: absolute !important;
  top: -1px;
  right: 0;
  width: 0px !important;
  height: 0px !important;
  -webkit-text-fill-color: #eee;
  border-top: 15px solid transparent;
  border-bottom: 15px solid transparent;
  border-left: 15px solid rgba(0, 0, 0, 0.5);
  // border-right: 10px solid #000;
  border-right: none;
}

i.icon-del {
  position: absolute !important;
  right: 10px;
  top: -2px;
  display: inline-block;
  width: 0px !important;
  height: 0px !important;
  font-weight: bold;
  color: #fff;
  font-style: normal;
}
span.add {
  padding: 0 !important;
  img {
    width: $item_width;
  }
}
.circle-solid {
  background: black;
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: none;
}
.circle-hollow {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  border: 1px solid #666666;
}
</style>
<style lang="scss">
#app,
#compare {
  height: 100%;
  .left {
    width: 60px;
    // margin-right: 20px;
  }
  .right {
    width: 60px;
    span {
      // margin: 5px;
      width: 60px;
      color: #6688ca;
      height: 100%;
      line-height: 400%;
    }
  }
}
#compare {
  display: flex;
  flex-direction: column;
}
.header-fix {
  position: initial !important;
}
</style>
